var ttc_timeline=function(conf){
  this.version='0.0.2';

	this.editor=parent;
	this.cur=[false,false];
	this.domObj=false;
	
	this.state={
	  mode:'select',
	  
	  frameNum:0,
	  layerNum:0,
	  
	  frameFrom:false,
	  frameTo:false,
	  layerFrom:false,
	  layerTo:false,
	  
	  frameRate:100
	};

	this.errors_log=[];   //Буффер ошибок
	this.err=function(txt){
	  this.errors_log.push(txt);
	  return false;
	}
	this.errors=function(){
	  return this.errors_log.join(' ');
	}
	this.error=function(){
	  return this.errors_log[ this.errors_log.length-1 ];
	}

	this.init=function(){
	  var t=document.getElementById( this.domID );
	  if( typeof(t)=='undefined' || !t ) return this.err('DOM object for Timeline undefined');
		this.domObj=t;

		this.apply();
		return true;
	}
	
	this.data={
		frameCnt:false,
    layerCnt:false,
    visibility:[]
	};

	this.valid=function(dt){
	  if(typeof(dt)=='undefined') return this.err('data: data not passed');
	  if(
			typeof(dt.frameCnt)		==	'undefined' ||
			typeof(dt.layerCnt)		==	'undefined' ||
			typeof(dt.visibility)			==	'undefined'
		)	return this.err('data: format error');
		return true;
	}

	this.set=function( dt ){
		if(!this.valid(dt)) return false;
	  this.data=dt;
	  if(!this.apply()) return false;
	  return true;
	}

  //Построение таймлайна по данным
	this.apply=function(){
	  if(!this.valid(this.data)) return false;

		this.domObj.innerHTML='<div id="tt_timeline_labels">'+
														'<div id="tt_timeline_tools">'+
		                        	'<span id="tt_timeline_tools_cells">'+
																'<a href="" onClick="tt_event(\'tlAddFrame\'); return false;">fa</a>'+
						    								'<a href="" onClick="tt_event(\'tlRemoveFrame\'); return false;">fr</a>'+
														    '<a href="" onClick="tt_event(\'tlAddLayer\'); return false;">la</a>'+
														    '<a href="" onClick="tt_event(\'tlRemoveFrame\'); return false;">lr</a>'+
														  /*
													    '</span><span id="tt_timeline_tools_modes">'+
													      '<a href="" onClick="tt_event(\'tlState\',{mode:\'select\'}); return false;">sel</a>'+
													      '<a href="" onClick="tt_event(\'tlState\',{mode:\'range\'}); return false;">range</a>'+
													      '<a href="" onClick="tt_event(\'tlState\',{mode:\'draft\'}); return false;">draft</a>'+
															'</span>'+
															*/
															'</span><span id="tt_timeline_tools_player">'+
													      '<a href="" id="tt_playTriggerBut" onClick="tt_event(\'tlPlayTrigger\'); return false;">&#9658;</a>'+
															'</span>'+
														'</div>'+
													'</div>'+
													'</div><div id="tt_timeline_frames">'+
														'<div id="tt_timeline_sysframes"></div>'+
													'</div>';

	  var lines={
	    topline_html:'',
	    levels:[],
	    labels:[]
		};

	  for(var fnum=0,cnt=this.data.frameCnt; fnum<cnt; fnum++ ){
	    for(var lnum=0,jcnt=this.data.layerCnt; lnum<jcnt; lnum++ ){
	      if(typeof(lines.levels[lnum])=='undefined') lines.levels[lnum]='';

        if(this.data.visibility[lnum]){
          var vis_act=false, vis_class='visible';
				}else{
				  var vis_act=true, vis_class='invisible';
				}

	      lines.levels[lnum]+=
					'<a href="#" id="cell_'+fnum+'_'+lnum+'" class="cell '+
					vis_class+
					'" onClick="tt_event(\'tlGetCanvas\',{fid:'+fnum+', lid:'+lnum+'}); return false;"><i>'+
					fnum+'</i></a>';
					
	      if( typeof( lines.labels[lnum] )=='undefined' ){
					lines.labels[lnum]=
					'<label>'+
						'<a href="" class="tt_layerBut" onClick="tt_event(\'tlGetLayer\',{layer:'+lnum+'}); return false;">'+
					 		'layer'+lnum+
					 	'</a>'+
						'<a href="" class="vis '+vis_class+'" onClick="tt_event(\'tlChange\',{\'act\':\'visibility\',lid:'+lnum+', visibility:'+vis_act+'}); return false;">'+
					 		vis_class+
					 	'</a>'+
					'</label>';
				}
	    }
		}

		var frames='';
		for(var i in lines.levels){
		  if( typeof(lines.levels[i])=='function' ) continue;
		  frames+='<div class="layer" id="layer_'+i+'">'+lines.levels[i]+'</div>';
		}

		var t=document.getElementById('tt_timeline_frames');
		t.innerHTML+=frames;

		t=document.getElementById('tt_timeline_labels');
		t.innerHTML+=lines.labels.join('');

    this.applyState();
		return true;
	}

	this.setState=function(state){
	  for(var i in state){
	    if(typeof(this.state[i])!='undefined'){
	      this.state[i]=state[i];
			}
		}
	}
	this.applyState=function(){
	  if( typeof(this.state)=='undefined' || !this.state ) return false;

		var t=this.domObj.getElementsByClassName('state');
		if(t.length>0) for(var i=0; i<t.length; i++){
			t[i].removeClassName('state active range');
		}

	  switch( this.state.mode ){
	    case 'range':{
	      if( this.state.frameNum===false ||
	          this.state.frameTo===false
				) return false;
				break;
			}
	    case 'draft':{
	      if( this.state.frameNum===false ) return false;
				break;
			}
	    case 'select':
	    default:{
	      if( this.state.frameNum===false || this.state.layerNum===false ) return false;
				var cell=document.getElementById('cell_'+this.state.frameNum+'_'+this.state.layerNum);
				if(!cell)	return false;
				else{
      		cell.addClassName('state active');
				}
			}
		}
		return true;
	}

	this.select=function(fnm,lnm){
	  this.setState({mode:'select',frameNum:fnm, layerNum:lnm});
	  if(!this.visibility(lnm)) this.visibility(lnm,true);
	  else
	  	this.applyState();
	}
	
	this.visibility=function(lid,vis){
	  if(lid>this.data.visibility.length-1) return false;
	  if(typeof(vis)=='undefined'){
	    return this.data.visibility[lid];
		}else{
			if(this.data.visibility[lid]!=vis){
		    this.data.visibility[lid]=vis;
		    this.apply();
			}
			return true;
		}
	}
	this.nextCell=function(){
	  if( ( this.state.frameNum +1 ) > this.data.frameCnt-1 ) this.state.frameNum=0;
	  else this.state.frameNum++;
	  this.applyState();
	}
	this.prevCell=function(){
	  if( ( this.state.frameNum -1 ) < 0 ) this.data.frameCnt-1;
	  else this.state.frameNum--;
	  this.applyState();
	}

	this.play=function(){
	  if(this.state.play) return true;
	  this.state.play=true;
	  var t=document.getElementById('tt_playTriggerBut');
	  t.addClassName('play'); t.innerHTML='&#9632;';//stop
	  this.playTimer=setInterval(function(){
	    this.nextCell();
		}.bind(this),this.state.frameRate);
	}
	this.stop=function(){
	  clearInterval(this.playTimer);
	  this.playTimer=false;
	  this.state.play=false;
	  var t=document.getElementById('tt_playTriggerBut');
	  t.removeClassName('play'); t.innerHTML='&#9658;';//play
	}
	
	/************
	 *  constructor - build and prepare self nesessaries
	 ***********/
	if(typeof(conf.parent)=='undefined'){
	  return this.err('conf.parent not passed');
	}
	this.editor=parent;

	if(typeof(conf.domID)=='undefined'){
	  return this.err('conf.domID not passed');
	}
	this.domID=conf.domID;

	if(typeof(conf.data)!='undefined')	this.set(conf.data);

	if(!this.init()) return false;
}